package controller

import (
	"crypto/rand"
	"fmt"
	"log"
	"math/big"
	"net/http"
	"software/config"
	"software/model"

	"github.com/gin-gonic/gin"
	"golang.org/x/crypto/bcrypt"
)

// 请求结构体
type LoginRequest struct {
	Email    string `json:"email" binding:"required,email"`
	Password string `json:"password" binding:"required"`
}

type LoginWithCodeRequest struct {
	Email string `json:"email" binding:"required,email"`
	Code  string `json:"code" binding:"required"`
}

type RegisterRequest struct {
	Name     string `json:"name" binding:"required"`
	Email    string `json:"email" binding:"required,email"`
	Password string `json:"password" binding:"required,min=6"`
	Code     string `json:"code" binding:"required"`
}

type SendCodeRequest struct {
	Email string `json:"email" binding:"required,email"`
}

type CheckEmailRequest struct {
	Email string `json:"email" binding:"required,email"`
}

type CheckEmailResponse struct {
	Success bool   `json:"success"`
	Message string `json:"message"`
	Exists  bool   `json:"exists"` // true表示邮箱已存在，false表示邮箱不存在
}

// 响应结构体
type Response struct {
	Success bool        `json:"success"`
	Message string      `json:"message"`
	Data    interface{} `json:"data,omitempty"`
	Token   string      `json:"token,omitempty"`
	User    interface{} `json:"user,omitempty"`
}

// 生成6位数字验证码
func generateCode() string {
	code := ""
	for i := 0; i < 6; i++ {
		num, _ := rand.Int(rand.Reader, big.NewInt(10))
		code += fmt.Sprintf("%d", num.Int64())
	}
	return code
}

// 发送验证码
func SendVerificationCode(c *gin.Context) {
	var req SendCodeRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		log.Printf("参数绑定错误: %v", err)
		c.JSON(http.StatusBadRequest, Response{
			Success: false,
			Message: "请求参数错误",
		})
		return
	}

	log.Printf("开始处理发送验证码请求，邮箱: %s", req.Email)

	// 生成验证码
	code := generateCode()
	log.Printf("生成验证码: %s", code)

	// 发送邮件
	err := config.SendVerificationCode(req.Email, code)
	if err != nil {
		log.Printf("发送邮件失败: %v", err)
		c.JSON(http.StatusInternalServerError, Response{
			Success: false,
			Message: "发送验证码失败",
		})
		return
	}
	log.Printf("邮件发送成功")

	// 保存验证码到数据库
	err = config.SaveVerificationCode(config.DB, req.Email, code)
	if err != nil {
		log.Printf("保存验证码到数据库失败: %v", err)
		c.JSON(http.StatusInternalServerError, Response{
			Success: false,
			Message: "保存验证码失败: " + err.Error(),
		})
		return
	}
	log.Printf("验证码保存到数据库成功")

	c.JSON(http.StatusOK, Response{
		Success: true,
		Message: "验证码发送成功",
	})
}

// 检查邮箱是否已注册
func CheckEmail(c *gin.Context) {
	var req CheckEmailRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		log.Printf("邮箱检查参数绑定错误: %v", err)
		c.JSON(http.StatusBadRequest, CheckEmailResponse{
			Success: false,
			Message: "请求参数错误",
			Exists:  false,
		})
		return
	}

	log.Printf("检查邮箱是否已注册: %s", req.Email)

	// 查找用户
	var user model.User
	err := config.DB.Where("email = ?", req.Email).First(&user).Error

	exists := err == nil // 如果找到用户，则邮箱已存在

	c.JSON(http.StatusOK, CheckEmailResponse{
		Success: true,
		Message: "检查完成",
		Exists:  exists,
	})
}

// 密码登录
func Login(c *gin.Context) {
	var req LoginRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, Response{
			Success: false,
			Message: "请求参数错误",
		})
		return
	}

	// 查找用户
	var user model.User
	err := config.DB.Where("email = ?", req.Email).First(&user).Error
	if err != nil {
		c.JSON(http.StatusUnauthorized, Response{
			Success: false,
			Message: "用户不存在",
		})
		return
	}

	// 验证密码
	err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password))
	if err != nil {
		c.JSON(http.StatusUnauthorized, Response{
			Success: false,
			Message: "密码错误",
		})
		return
	}

	// 生成JWT令牌
	token, err := config.GenerateToken(&user)
	if err != nil {
		c.JSON(http.StatusInternalServerError, Response{
			Success: false,
			Message: "生成令牌失败",
		})
		return
	}

	c.JSON(http.StatusOK, Response{
		Success: true,
		Message: "登录成功",
		Token:   token,
		User:    user,
	})
}

// 验证码登录
func LoginWithCode(c *gin.Context) {
	var req LoginWithCodeRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, Response{
			Success: false,
			Message: "请求参数错误",
		})
		return
	}

	// 验证验证码
	valid, err := config.ValidateVerificationCode(config.DB, req.Email, req.Code)
	if err != nil {
		c.JSON(http.StatusInternalServerError, Response{
			Success: false,
			Message: "验证码验证失败",
		})
		return
	}

	if !valid {
		c.JSON(http.StatusUnauthorized, Response{
			Success: false,
			Message: "验证码错误或已过期",
		})
		return
	}

	// 查找用户
	var user model.User
	err = config.DB.Where("email = ?", req.Email).First(&user).Error
	if err != nil {
		c.JSON(http.StatusUnauthorized, Response{
			Success: false,
			Message: "用户不存在",
		})
		return
	}

	// 生成JWT令牌
	token, err := config.GenerateToken(&user)
	if err != nil {
		c.JSON(http.StatusInternalServerError, Response{
			Success: false,
			Message: "生成令牌失败",
		})
		return
	}

	c.JSON(http.StatusOK, Response{
		Success: true,
		Message: "登录成功",
		Token:   token,
		User:    user,
	})
}

// 注册
func Register(c *gin.Context) {
	var req RegisterRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		log.Printf("注册参数绑定失败: %v", err)
		c.JSON(http.StatusBadRequest, Response{
			Success: false,
			Message: "请求参数错误: " + err.Error(),
		})
		return
	}

	// 验证验证码
	valid, err := config.ValidateVerificationCode(config.DB, req.Email, req.Code)
	if err != nil {
		c.JSON(http.StatusInternalServerError, Response{
			Success: false,
			Message: "验证码验证失败",
		})
		return
	}

	if !valid {
		c.JSON(http.StatusUnauthorized, Response{
			Success: false,
			Message: "验证码错误或已过期",
		})
		return
	}

	// 检查邮箱是否已存在
	var existingUser model.User
	err = config.DB.Where("email = ?", req.Email).First(&existingUser).Error
	if err == nil {
		c.JSON(http.StatusConflict, Response{
			Success: false,
			Message: "邮箱已被注册",
		})
		return
	}

	// 加密密码
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
	if err != nil {
		c.JSON(http.StatusInternalServerError, Response{
			Success: false,
			Message: "密码加密失败",
		})
		return
	}

	// 创建用户
	user := model.User{
		Name:     req.Name,
		Email:    req.Email,
		Password: string(hashedPassword),
		Role:     "user",
	}

	err = config.DB.Create(&user).Error
	if err != nil {
		c.JSON(http.StatusInternalServerError, Response{
			Success: false,
			Message: "用户创建失败",
		})
		return
	}

	// 生成JWT令牌
	token, err := config.GenerateToken(&user)
	if err != nil {
		c.JSON(http.StatusInternalServerError, Response{
			Success: false,
			Message: "生成令牌失败",
		})
		return
	}

	c.JSON(http.StatusOK, Response{
		Success: true,
		Message: "注册成功",
		Token:   token,
		User:    user,
	})
}

// 更新密码
func UpdatePassword(c *gin.Context) {
	c.JSON(http.StatusOK, Response{
		Success: true,
		Message: "密码更新成功",
	})
}
